#ifndef _SOCK_HPP
#define _SOCK_HPP

#include <iostream>
#include <cstring>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>

class Sock
{
    private:
    public:
        static int Socket()
        {
            int listen_sock = socket(AF_INET, SOCK_STREAM, 0);
            if(listen_sock == -1)
            {
                fprintf(stderr, "Socket error!\n");
                exit(1);
            }

            std::cout << "Socket success!" << std::endl;

            // 设置取消TIME_WAIT
            int opt = 1;
            if(setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1)
            {
                  fprintf(stderr, "setsockopt: %s\n", strerror(errno));
            }
            return listen_sock;
        }

        static void Bind(int listen_sock, uint16_t port)
        {
            struct sockaddr_in local;
            bzero(&local, sizeof(local));
            local.sin_family = AF_INET;
            local.sin_port = htons(port);
            local.sin_addr.s_addr = INADDR_ANY;
            if(bind(listen_sock, reinterpret_cast<struct sockaddr*>(&local), sizeof(local)) == -1)
            {
                fprintf(stderr, "Bind error!\n");
                exit(1);
            }

        }

        static void Listen(int listen_sock)
        {
            const int BACKLOG = 5;
            if(listen(listen_sock, BACKLOG) == -1)
            {
                fprintf(stderr, "Listen error!\n");
                exit(1);
            }
            
            std::cout << "Listen success!" << std::endl;
        }

        static int Accept(int listen_sock)
        {
            struct sockaddr_in peer;
            bzero(&peer, sizeof(peer));
            socklen_t len = sizeof(peer);
            int fd = accept(listen_sock, reinterpret_cast<struct sockaddr*>(&peer), &len);
            if(fd == -1)
            {
                fprintf(stderr, "Accept error!\n");
                exit(1);
            }

            return fd;
        }
};

#endif
